#include "CPrimPlan.h"

CPrimPlan ::CPrimPlan(const CPoint3f& p1, const CPoint3f& p2, const CPoint3f& p3):IPrimitive()
{
	m_p1=p1; m_p2=p2; m_p3=p3;

	CVector3f v1 = p2 - p1;
	CVector3f v2 = p3 - p1;
	m_normal = v1.cross(v2);
	m_normal.normalize();

	m_A = m_normal.x;
	m_B = m_normal.y;
	m_C = m_normal.z;
	
	m_D = -m_A * p1.x - m_B * p1.y - m_C * p1.z;

	m_point = p1;
}

CPrimPlan::~CPrimPlan(){}

bool CPrimPlan::intersect(const CRay& ray, float& dist, bool useGlobalCoordinates)
{
	//change the coordinate system
	CRay r;
	if (useGlobalCoordinates)
		globalToLocal(ray, r);
	else
		convertRayToLocalCoordinates(ray, r);

	float denom = m_normal.dot(r.getDirection());

	CVector3f temp = r.getOrigin() - m_point;
	//temp.normalize();
	float num = m_normal.dot(temp);

	if(denom == 0)
		return false;

	float t = -num/denom;

	if(t<=0.1f)
		return false;

	dist = t;
	return true;
}

void CPrimPlan::computeNormal(const CRay& ray, float /*dist*/, CVector3f& normal)const
{
	//store the local normal
	normal.x = m_A;
	normal.y = m_B;
	normal.z = m_C;

	//reset to the global coordinate systeme
	convertNormalToGlobalCoordinates(normal, normal);

	//get the opposite normal if needed
	float dot = normal.dot(ray.getDirection());
	if (dot > 0)
		normal *= -1;

}

bool CPrimPlan::isInside(const CVector3f& p)const
{
	//convert p to local coordinates
	CVector3f localP;
	convertPointToLocalCoordinates(p, localP);

	//check distance between the point and the plan. If 0 return true
	//equation d(A,P) = (ax * Pa + ay * Pb + az * Pc + Pd) / (||n||)
	double num = m_normal.dot(localP) + m_D;
	double denum = m_normal.norme();

	double dist = num / denum;
	if(dist == 0)
		return true;

	return false;
}

